#include "cbb_ph_m01_dis.h"
#include <string.h>

// 固定帧头
#define M01_DIS_HEAD 0xAA

// BCD转换倍率
const uint32_t u32BCD[4]= {1000000,10000,100,1};

PH_REG_DEF(cbb_m01_dis, PH_M01_Dis_t)

PH_RET_t
cbb_m01_dis_set_data(PH_t* pstSelf, M01_Dis_Data_t* pstData){

    // 校验参数
    if(NULL == pstSelf || NULL == pstData || NULL == pstSelf->pvFeature) return PH_ERR;

    // 获取modbus上下文
    PH_M01_Dis_t* pstM01Dis = GET_PH(pstSelf, PH_M01_Dis_t);

    // 复制数据到备份
    memcpy(&pstM01Dis->stData, pstData, sizeof(M01_Dis_Data_t));
    
    // 返回成功
    return PH_OK;
}

PH_RET_t
cbb_m01_dis_get_data(PH_t* pstSelf, M01_Dis_Data_t* pstData)
{
    // 校验参数
    if(NULL == pstSelf || NULL == pstData || NULL == pstSelf->pvFeature) return PH_ERR;

    // 获取modbus上下文
    PH_M01_Dis_t* pstM01Dis = GET_PH(pstSelf, PH_M01_Dis_t);

    // 复制数据到参数
    memcpy(pstData, &pstM01Dis->stData, sizeof(M01_Dis_Data_t));
    
    // 返回成功
    return PH_OK;
}

PH_RET_t 
cbb_m01_dis_build(PH_t* pstSelf, PH_Buf_t* pstTxBuffer){
    
    // 校验参数
    if(NULL == pstTxBuffer || NULL == pstTxBuffer->pu8Buffer || 9 > pstTxBuffer->u32BufferLen) return PH_ERR;

    // 校验参数
    if(NULL == pstSelf || NULL == pstSelf->pvFeature || NULL == pstSelf->pfnAppend) return PH_ERR;

    // 获取modbus上下文
    PH_M01_Dis_t* pstM01Dis = GET_PH(pstSelf, PH_M01_Dis_t);

    // 获取数据
    M01_Dis_Data_t* pstData = &(pstM01Dis->stData);

    // 报文长度
    uint32_t u32Len = 0;

    // 提取数据
    uint8_t* pu8Request     = pstTxBuffer->pu8Buffer;
    uint8_t u8Addr          = pstData->u8Addr;

    // 添加协议头和地址
    pu8Request[u32Len++] = M01_DIS_HEAD;
    pu8Request[u32Len++] = u8Addr;

    // 添加功能码
    pu8Request[u32Len++] = 0x00;
    pu8Request[u32Len++] = pstData->u16Func;

    // 添加数据码
    pu8Request[u32Len++] = 0x00;
    pu8Request[u32Len++] = 0x01;
    pu8Request[u32Len++] = (pstData->u32Data >> 8) & 0xFF;
    pu8Request[u32Len++] = pstData->u32Data & 0xFF;

    // 追加add8校验
    u32Len--; // 协议头不参与校验
    uint8_t u8Ret = pstSelf->pfnAppend(pu8Request + 1, &u32Len);
    if(!u8Ret) return PH_ERR;

    // 追加协议头长度
    u32Len++;

    // 更新长度返回成功
    pstTxBuffer->u32DataLen = u32Len;
    return PH_OK;
}
 
PH_RET_t 
cbb_m01_dis_parse(PH_t* pstSelf, PH_Buf_t* pstRxBuffer){

    // 校验参数
    if(NULL == pstRxBuffer || NULL == pstRxBuffer->pu8Buffer || 9 > pstRxBuffer->u32DataLen) return PH_ERR;

    // 校验参数
    if(NULL == pstSelf || NULL == pstSelf->pvFeature || NULL == pstSelf->pfnCheck) return PH_ERR;

    // 校验
    uint32_t u32Len = pstRxBuffer->u32DataLen - 1; // 协议头不参与校验
    uint8_t u8Ret = pstSelf->pfnCheck(pstRxBuffer->pu8Buffer + 1, u32Len);
    if(!u8Ret) return PH_ERR;

    // 获取modbus上下文
    PH_M01_Dis_t* pstModbus = GET_PH(pstSelf, PH_M01_Dis_t);

    // 获取数据
    M01_Dis_Data_t* pstData = &(pstModbus->stData);

    // 提取数据
    uint8_t* pu8Response    = pstRxBuffer->pu8Buffer;
    uint8_t u8Addr          = pu8Response[1];
    uint16_t u16Func        = pu8Response[2]*256 + pu8Response[3];

    // 判断与上一次是否一致
    if(M01_DIS_HEAD !=  pu8Response[0] || u8Addr !=  pstData->u8Addr || u16Func !=  pstData->u16Func) return PH_ERR;

    switch(u16Func){
        case M01_DIS_SET_OFFSET:{

            // 校验长度
            if(13 != pstRxBuffer->u32DataLen) return PH_ERR;

            // 解析数据
            uint32_t u32Data = pu8Response[6] * 256 + pu8Response[7];

            // 判断是否设置成功
            if(u32Data != pstData->u32Data) return PH_ERR;

            break;
        }
        case M01_DIS_READ_CONTINUOUS:
        case M01_DIS_READ_ONCE:{

            // 校验长度
            if(13 != pstRxBuffer->u32DataLen) return PH_ERR;

            // 解析数据
            uint32_t u32Data = 0;
            for(int i=0; i<4; i++){
                uint8_t u8Data = pu8Response[6+i];
                uint16_t u16Data = (((u8Data / 16) & 0x0F) * 10) + (u8Data & 0x0F);
                u32Data += u16Data * u32BCD[i];
            }

            // 保存数据
            pstData->u32Data = u32Data;

            break;
        }
    }

    // 返回成功
    return PH_OK;
}
